package leetcode.od;

import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * .
 * 背包问题--背包问题中的子背包问题
 *
 * @author pppppp
 * @date 2022/3/7 10:28
 * 描述
 * 王强今天很开心，公司发给N元的年终奖。王强决定把年终奖用于购物，他把想买的物品分为两类：
 * 主件与附件，附件是从属于某个主件的，下表就是一些主件与附件的例子：
 * <p>
 * 主件	附件
 * 电脑	打印机，扫描仪
 * 书柜	图书
 * 书桌	台灯，文具
 * 工作椅	无
 * <p>
 * 如果要买归类为附件的物品，必须先买该附件所属的主件，且每件物品只能购买一次。每个主件可以有 0 个、 1 个或 2 个附件。
 * 附件不再有从属于自己的附件。
 * 王强想买的东西很多，为了不超出预算，他把每件物品规定了一个重要度，分为 5 等：用整数 1 ~ 5 表示，第 5 等最重要。
 * 他还从因特网上查到了每件物品的价格（都是 10 元的整数倍）。他希望在不超过 N 元（可以等于 N 元）的前提下，
 * 使每件物品的价格与重要度的乘积的总和最大。
 * 设第 j 件物品的价格为 v[j] ，重要度为 w[j] ，共选中了 k 件物品，编号依次为 j 1 ， j 2 ，……， j k ，则所求的总和为：
 * v[j 1 ]*w[j 1 ]+v[j 2 ]*w[j 2 ]+ … +v[j k ]*w[j k ] 。（其中 * 为乘号）
 * 请你帮助王强设计一个满足要求的购物单。
 * <p>
 * <p>
 * 输入描述：
 * 输入的第 1 行，为两个正整数，用一个空格隔开：N m
 * <p>
 * （其中 N （ N<32000 ）表示总钱数， m （m <60 ）为希望购买物品的个数。）
 * 从第 2 行到第 m+1 行，第 j 行给出了编号为 j-1 的物品的基本数据，每行有 3 个非负整数 v p q
 * <p>
 * （其中 v 表示该物品的价格（ v<10000 ）， p 表示该物品的重要度（ 1 ~ 5 ）， q 表示该物品是主件还是附件。
 * 如果 q=0 ，表示该物品为主件，如果 q>0 ，表示该物品为附件， q 是所属主件的编号）
 * <p>
 * 输出描述：
 * 输出文件只有一个正整数，为不超过总钱数的物品的价格与重要度乘积的总和的最大值（ <200000 ）。
 * 示例1
 * 输入：
 * 1000 5
 * 800 2 0
 * 400 5 1
 * 300 5 1
 * 400 3 0
 * 500 2 0
 * <p>
 * 输出：
 * 2200
 * <p>
 * 示例2
 * 输入：
 * 50 5
 * 20 3 5
 * 20 3 5
 * 10 3 0
 * 10 2 0
 * 10 1 0
 * <p>
 * 输出：
 * 130
 * <p>
 * 说明：
 * 由第1行可知总钱数N为50以及希望购买的物品个数m为5；
 * 第2和第3行的q为5，说明它们都是编号为5的物品的附件；
 * 第4~6行的q都为0，说明它们都是主件，它们的编号依次为3~5；
 * 所以物品的价格与重要度乘积的总和的最大值为10*1+20*3+20*3=130
 */
public class _HJ16_购物单 {

    @Test
    public void T_review(){

    }
    public static void main(String[] args) {
        int[][] nums = {{50, 5}, {20, 3, 5}, {20, 3, 5}, {10, 3, 0}, {10, 2, 0}, {10, 1, 0}};
        int n = nums[0][0], m = nums[0][1];
        HashMap<Integer, Goods> map = new HashMap<>();
        for (int i = 1; i < nums.length; i++) {
            if (nums[i][2] == 0 && map.containsKey(i)) {
                continue;
            }

            if (nums[i][2] == 0) {
                map.put(i, new Goods(nums[i][0], nums[i][1], new ArrayList<>()));
            } else {
                Goods son = new Goods(nums[i][0], nums[i][1], new ArrayList<>());
                if (map.containsKey(nums[i][2])) {
                    Goods goods = map.get(nums[i][2]);
                    goods.son.add(son);
                } else {
                    ArrayList<Goods> goods = new ArrayList<>();
                    goods.add(son);
                    Goods fa = new Goods(nums[nums[i][2]][0], nums[nums[i][2]][1], goods);
                    map.put(nums[i][2], fa);
                }
            }
        }
        Goods[] goods = new Goods[map.size()];
        int [][] prices = new int[goods.length+1][3];
        int [][] priceMultiplyPriority = new int[goods.length+1][3];
        int index = 1;
        for (Integer key : map.keySet()) {
            Goods g = map.get(key);
            prices[index][0] = g.price;
            priceMultiplyPriority[index][0] = g.price * g.value;
            ArrayList<Goods> son = g.son;
            if(son.size() == 1){
                prices[index][1] = son.get(0).price;
                priceMultiplyPriority[index][1] = son.get(0).price *  son.get(0).value;

            } else if(son.size() == 2){
                prices[index][1] = son.get(0).price;
                priceMultiplyPriority[index][1] = son.get(0).price *  son.get(0).value;

                prices[index][2] =  son.get(1).price;
                priceMultiplyPriority[index][2] = son.get(1).price *  son.get(1).value;
            }
            index++;
        }

        int[][] dp = new int[goods.length+1][n+1];
        for (int i = 1; i <= goods.length; i++) {
            for (int j = 1; j <= n ; j++) {
                int a = prices[i][0], b = priceMultiplyPriority[i][0];
                int c = prices[i][1], d = priceMultiplyPriority[i][1];
                int e = prices[i][2], f = priceMultiplyPriority[i][2];
                dp[i][j] = j >= a ? Math.max(dp[i-1][j-a] + b, dp[i-1][j]) : dp[i-1][j];
                dp[i][j] = j >= (a+c) ? Math.max(dp[i-1][j-a-c] + b + d, dp[i][j]) : dp[i][j];
                dp[i][j] = j >= (a+e) ? Math.max(dp[i-1][j-a-e] + b + f, dp[i][j]) : dp[i][j];
                dp[i][j] = j >= (a+c+e) ? Math.max(dp[i-1][j-a-c-e] + b + d + f, dp[i][j]) : dp[i][j];
            }
            System.out.println();
        }
        System.out.println(dp[goods.length][n]);
    }


}

class Goods {
    public Integer price;
    public Integer value;
    public ArrayList<Goods> son;

    public Goods() {

    }

    public Goods(int price, int value, ArrayList<Goods> son) {
        this.price = price;
        this.value = value;
        this.son = son;
    }
}